from PySide2.QtWidgets import QStyledItemDelegate, QLineEdit
from PySide2.QtGui import QCursor, QPalette
from PySide2.QtCore import Qt, QRect, QSize

class myDelegate(QStyledItemDelegate):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.sub = 0.4         # 备注编辑器宽度占比
        self.margin = 5        # 主编辑器和备注编辑器间距

    def initStyleOption(self, option, index):
        '''初始化样式选项,主文本显示行号'''
        super().initStyleOption(option, index)
        main_text = index.data(Qt.DisplayRole)        
        option.text = f'{index.row()}. {main_text}'

    def createEditor(self, parent, option, index):
        '''根据鼠标点击位置创建不同的编辑器'''
        pos = parent.mapFromGlobal(QCursor.pos())
        rect = option.rect
        # 点击主文本，则显示主文本编辑器
        if self.mainRect(rect).contains(pos):
            editor = QLineEdit(parent)
            editor.setObjectName("mainEditor")
            return editor
        # 点击备注，则显示备注编辑器
        if self.subRect(rect).contains(pos):
            editor = QLineEdit(parent)
            editor.setObjectName("subEditor")
            return editor
        return None

    def setEditorData(self, editor, index):
        '''模型数据加载到编辑器'''
        # 加载主文本
        if editor.objectName() == "mainEditor":
            text = index.data(Qt.DisplayRole)
            editor.setText(text)
        # 加载备注
        elif editor.objectName() == "subEditor":
            text = index.data(Qt.UserRole + 1)
            editor.setText(text)

    def setModelData(self, editor, model, index):
        '''编辑器数据保存到模型数据'''
        # 保存主文本
        if editor.objectName() == "mainEditor":
            text = editor.text()
            model.setData(index, text, Qt.DisplayRole)
        # 保存备注
        elif editor.objectName() == "subEditor":
            text = editor.text()
            model.setData(index, text, Qt.UserRole + 1)

    def updateEditorGeometry(self, editor, option, index):
        '''更新编辑器位置'''
        parent = editor.parent()
        if not parent: return
        pos = parent.mapFromGlobal(QCursor.pos())
        rect = option.rect
        # 点击主文本，则更新主文本编辑器位置
        if self.mainRect(rect).contains(pos):
            editor.setGeometry(self.mainRect(rect))
        # 点击备注，则更新备注编辑器位置
        elif self.subRect(rect).contains(pos):
            editor.setGeometry(self.subRect(rect))

    def paint(self, painter, option, index):
        '''自定义绘制'''
        super().paint(painter, option, index)
        # 获取备注数据和区域
        sub_text = index.data(Qt.UserRole + 1)
        sub_rect = self.subRect(option.rect)
        # 绘制备注编辑器，有备注显示备注，无备注显示提示文字
        if sub_text:
            painter.save()
            painter.setPen(option.palette.color(QPalette.Text))
            painter.drawText(sub_rect, Qt.AlignVCenter | Qt.AlignLeft, sub_text)
            painter.restore()
        else:
            painter.save()
            painter.setPen(option.palette.color(QPalette.PlaceholderText))
            painter.drawText(sub_rect, Qt.AlignVCenter | Qt.AlignLeft, "请输入备注")
            painter.restore()

    def sizeHint(self, option, index):
        '''设置项的大小'''
        size = super().sizeHint(option, index)
        return QSize(size.width() + self.sub + self.margin, size.height())  
        
    def mainRect(self, rect):
        '''获取主编辑区域'''
        return QRect(rect.left(), 
                    rect.top(), 
                    int(rect.width() * (1 - self.sub) - self.margin), 
                    rect.height())

    def subRect(self, rect):
        '''获取子编辑区域'''
        return QRect(rect.right() - int(rect.width() * self.sub), 
                    rect.top(), 
                    int(rect.width() * self.sub), 
                    rect.height())
